﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Globalization;

namespace SecureCookie.Implementation.Protocol
{
    /// <summary>
    /// Helper methods to set and get the data from a <see cref="HttpCookie"/>.
    /// </summary>
    public static class HttpCookieWrapper
    {
        private const string KEY_FOR_HASH_PART = "_";
        private const string KEY_FOR_EXPIRATION_PART = "__";
        private const string KEY_FOR_DATA_PART = "___";
        /// <summary>
        /// Returns the part of the cookie that contains the validation hash.
        /// </summary>
        /// <param name="cookie">The cookie from which the hash should be returned</param>
        /// <returns>The part of the cookie that contains the validation hash</returns>
        public static string GetHashPart(this HttpCookie cookie)
        {
            return cookie.Values[KEY_FOR_HASH_PART];
        }
        /// <summary>
        /// Sets the validation hash on a <see cref="HttpCookie"/>
        /// </summary>
        /// <param name="cookie">The cookie in which the validation hash should be added</param>
        /// <param name="value">The hash value to set</param>
        public static void SetHashPart(this HttpCookie cookie, string value)
        {
            cookie.Values[KEY_FOR_HASH_PART] = value;
        }
        /// <summary>
        /// Gets the original value from a secured <see cref="HttpCookie"/>
        /// </summary>
        /// <param name="cookie">The cookie to get the value from</param>
        /// <returns>The original value from a secured <see cref="HttpCookie"/></returns>
        public static string GetDataPart(this HttpCookie cookie)
        {
            return cookie.Values[KEY_FOR_DATA_PART];
        }
        /// <summary>
        /// Sets the original value inside a secured <see cref="HttpCookie"/>
        /// </summary>
        /// <param name="cookie">The cookie in which the original value should be added</param>
        /// <param name="value">The original value inside a secured <see cref="HttpCookie"/></param>
        public static void SetDataPart(this HttpCookie cookie, string value)
        {
            cookie.Values[KEY_FOR_DATA_PART] = value;
        }
        /// <summary>
        /// Sets the expiration datetime in a secured <see cref="HttpCookie"/>
        /// </summary>
        /// <param name="cookie">The cookie in which the expiration datetime should be added</param>
        /// <param name="expirationDate">The expiration datetime to add</param>
        public static void SetExpirationPart(this HttpCookie cookie, DateTime expirationDate)
        {
            cookie.Values[KEY_FOR_EXPIRATION_PART] = expirationDate.Ticks.ToString(CultureInfo.InvariantCulture);
        }
        /// <summary>
        /// Gets the expiration datetime from a secured <see cref="HttpCookie"/> 
        /// </summary>
        /// <param name="cookie">The secured <see cref="HttpCookie"/> from which the expiration datetime should be extracted</param>
        /// <returns>Null when not a secured cookie is being used or an invalide datetime is set inside the cookie. Otherwise the expiration datetime from the secured <see cref="HttpCookie"/></returns>
        public static DateTime? GetExpirationPart(this HttpCookie cookie)
        {
            var ticksAsString = cookie.Values[KEY_FOR_EXPIRATION_PART];
            if (!string.IsNullOrEmpty(ticksAsString))
            {
                long result;
                if (long.TryParse(ticksAsString, out result))
                    return new DateTime(result);
            }
            return null;
        }
    }
}
